# coding=utf-8


from components.guide import guide
from utils.Schedule import schedule_task
import shutil
import time
import copy
import multiprocessing
from multiprocessing import Process
import xml.dom.minidom
from services.resourcesservice import resourcesservice
from persistents import RedisServices
import os
from components.logger import logger
import datetime
import random
from managers import app_config
from utils.TimeUtils import calc_exec_during_timing
from utils.ExcelUtils import DevicesManagerTask


class monkeyservices(object):

    def __init__(self):
        self.resource = resourcesservice()
        self.rds_handler = RedisServices()

    # @schedule_task
    # def worker(self, params):
    #     """
    #         执行打包, 刷机, 跳过引导项, 执行monkey任务
    #
    #     :param params: 任务入参
    #     :return: 返回None
    #     """
    #     result = str(os.getppid()) + "_" + str(os.getpid())
    #     pname = multiprocessing.current_process().name
    #     logger.info("执行%s的任务" % (pname,))
    #     logger.info("执行入参:" + str(params))
    #     if str(params[4]) == "1":
    #         logger.info("执行%s的任务. 有3此构建ROM包的机会" % (pname,))
    #         # 给三次构建rom包的机会，已防止构建失败和构建超市
    #         status = False
    #         url = None
    #         if app_config.env:
    #             for trytimes in xrange(3):
    #                 logger.info("执行%s的任务. 尝试第%s次构建ROM包" % (pname, trytimes))
    #                 status, url = self.resource.getRom(params)
    #                 logger.info('%s, %s' % (str(status), str(url)))
    #                 if status and url is not None:
    #                     logger.info("执行%s的任务, 尝试第%s次构建成功" % (pname, trytimes))
    #                     break
    #         else:
    #             status = True
    #             url = "http://corgi.pt.miui.com/open-api/build/793231/out/polaris_images_1.1.1_20190115.0000.00_9.0_cn_98eee7d0a1.tgz"
    #         if status:
    #             if not url.startswith('http://'):
    #                 url = "http://" + url
    #             logger.info("获取ROM包的url： %s" % (str(url),))
    #             # 构建成功，下载并解压到对应目录
    #             flashscriptpath = self.resource.my_localsystem.downloadRomAndTarOpen(url)
    #             tims = 0
    #             logger.info("执行%s的任务, 有2次刷机机会" % (pname,))
    #             # 给两次刷包机会，应对可能存在的刷包问题
    #             while True:
    #                 if tims > 1:
    #                     break
    #                 try:
    #                     logger.info("执行%s的任务, 开始刷机" % (pname,))
    #                     # 刷机
    #                     if self.resource.getDeviceBySn(params[0]).flashdevice(flashscriptpath=flashscriptpath):
    #                         # 跳过引导页
    #                         logger.info("执行%s的任务, 开始处理引导页" % (pname,))
    #                         times_guide = 0
    #                         flag_jump_guide = False
    #                         while True:
    #                             if times_guide > 1:
    #                                 break
    #                             if guide(self.resource.getDeviceBySn(params[0])).handleGuidePage():
    #                                 logger.info("执行%s的任务, 刷机成功，已跳过引导，进入手机主界面。" % (pname,))
    #                                 result += "1.刷机成功，已跳过引导，进入手机主界面。"
    #                                 flag_jump_guide = True
    #                                 break
    #                             times_guide += 1
    #                             logger.info("执行%s的任务, 刷机成功，跳过引导页第%s次失败。" % (pname, str(times_guide)))
    #                         if flag_jump_guide:
    #                             break
    #                 except Exception, e:
    #                     logger.info("执行%s的任务, Exceptions %s。" % (pname, str(e.message)))
    #                     tims += 1
    #                     continue
    #                 except xml.parsers.expat.ExpatError, e:
    #                     logger.info("执行%s的任务, ExpatError %s。" % (pname, str(e.message)))
    #                     tims += 1
    #                     continue
    #             logger.info("执行%s的任务, 清除下载的rom文件和解压缩后的文件" % (pname,))
    #             # '清除下载的rom文件和解压缩后的文件'
    #             romfile = url.split('/')[-1]
    #             romtarfile = romfile.strip('.tgz')
    #             print '清除的rom文件和文件夹是：', romfile, romtarfile
    #             if os.path.exists('./' + romfile):
    #                 os.remove('./' + romfile)
    #             if os.path.exists('./' + romtarfile):
    #                 shutil.rmtree('./' + romtarfile)
    #             logger.info("执行%s的任务, 清除下载的rom文件和解压缩后的文件结果 %s %s" % (
    #                 pname, str(os.path.exists('./' + romfile)), str(os.path.exists('./' + romtarfile))))
    #
    #     if str(params[5]) == "1":
    #         logger.info("执行%s的任务, 开始monkey测试" % (pname,))
    #         # monkey测试
    #         if app_config.env:
    #             # weekday = datetime.datetime.now().weekday()
    #             hour = datetime.datetime.now().hour + 1
    #             # eventcount = (24 - hour) * 3600 * 2
    #             if hour < 9 and 9 - hour > 2:
    #                 # eventcount = (24 - hour) * 3600 * 2
    #                 eventcount = (9 - hour) * 3600 * 2
    #             else:
    #                 logger.info("没有过多的时间进行monkey测试了: %s" % str(9 - hour))
    #                 return
    #             # if weekday in (0,):
    #             # eventcount += 24 * 2 * 3600 * 2
    #         else:
    #             eventcount = 600
    #         monkeycmd = params[-2].replace('100000', str(eventcount))
    #         seedno = random.randint(100, 1000)
    #         monkeycmd = monkeycmd.replace('1000', str(seedno))
    #         logger.info("执行的monkey指令是: %s" % str(monkeycmd))
    #         self.resource.getDeviceBySn(params[0]).setScreenOn()
    #         if self.resource.getDeviceBySn(params[0]).monkey_test(monkeycmd):
    #             logger.info("执行%s的任务, 执行monkey测试结束" % (pname,))
    #             result += "2. 执行monkey测试结束。"
    #     # 充值使用的机型状态
    #     self.resource.resetDeviceWorkState(params[0])

    def get_devices_has_state(self):
        """
        处理获取当前连接电脑的移动终端的状态请求
        数据结构：{devices: [{product: "polaris_BUSY", sn: "2644fefa"}]}
        """
        devices = {"devices": self.resource.getAllDevicesWorkState()}
        for d in devices['devices']:
            self.rds_handler.hset(app_config.devices_history, d['sn'], d['product'].split(app_config.spec)[0])
        return devices

    def execute_monkey_new(self, params):
        """
        处理走起操作
        {u'pct_syskeys': u'0', u'pct_nav': u'20', u'pct_touch': u'30', u'seed': u'1000', u'pkg': u'', u'long_time': u'18', u'errhandler': u'--ignore-crashes;--ignore-timeouts;--ignore-security-exceptions;--kill-process-after-error;--monitor-native-crashes;', u'pct_appswitch': u'5', u'monkey': 1, u'area': u'cn', u'weekdays': u'0;1;2;3;4;5;6;', u'version': u'o-dev', u'pct_motion': u'20', u'build': 1, u'pct_anyevent': u'10', u'iter_time': u'00:00:00 - 23:00:00', u'device': u'', u'execpolicy': u'1', u'point_time': u'2019-01-09 00:00:00', u'throttle': u'500', u'package': u'', u'loglevel': u'-v', u'eventsnumber': u'100000', u'pct_majornav': u'15', u'pct_trackball': u'0'}
        """
        logger.info("开始执行monkey任务，入参%s" % params)
        # 根据界面操作的结果拼接monkey指令
        monkeycmd = "'monkey"
        packages = []
        packages.extend(params['pkg'].split(';'))
        packages.extend(params['package'].split(';'))
        # 去重
        packages = [p for p in list(set(packages)) if p != ""]
        logger.debug("包信息:" + str(packages))
        for pg in packages:
            monkeycmd += " -p " + pg
        monkeycmd += " " + params['loglevel'] + " --throttle " + \
                     params['throttle'] + " -s " + params['seed']
        for errignore in params['errhandler'].split(';'):
            monkeycmd += " " + errignore
        if params['pct_touch']:
            monkeycmd += " --pct-touch " + params['pct_touch']
        if params['pct_motion']:
            monkeycmd += " --pct-motion " + params['pct_motion']
        if params['pct_trackball']:
            monkeycmd += " --pct-trackball " + params['pct_trackball']
        if params['pct_nav']:
            monkeycmd += " --pct-nav " + params['pct_nav']
        if params['pct_majornav']:
            monkeycmd += " --pct-majornav " + params['pct_majornav']
        if params['pct_syskeys']:
            monkeycmd += " --pct-syskeys " + params['pct_syskeys']
        if params['pct_appswitch']:
            monkeycmd += " --pct-appswitch " + params['pct_appswitch']
        if params['pct_anyevent']:
            monkeycmd += " --pct-anyevent " + params['pct_anyevent']
        monkeycmd += " --bugreport " + \
                     params['eventsnumber'] + " > /sdcard/monkey.log'"
        logger.debug("monkey指令信息:" + str(monkeycmd))
        # 如果未选择机型，对IDLE状态的机型进行操作，如果选择机型对制定机型进行操作
        devices = []
        if params['device']:
            # self.resource.setDeviceWorkStateBusy(str(params['device']))
            devices.append(str(params['device']))
        else:
            # self.resource.setAllIdleDevicesBusy()
            devices = self.resource.getIdleDevices()
            devices.extend(self.resource.getDevicesInFastbootMode())
        logger.info("参加执行的Android设备有:" + str(devices))
        # 构建Process入参，[省略的打包机型， 打包版本， 包适配的区域， 是否需要打包， 是否执行monkey测试， 当前的连接到电脑的设备信息（占时未使用到）， 拼接的monkey测试指令， monkey测试的开始时间]
        argus = ["", params['version'], params['area'], params['build'],
                 params['monkey'], monkeycmd, '0', params['execpolicy'], params['weekdays'], params['iter_time'],
                 params['long_time'], params['point_time']]
        if str(argus[3]) == "0" and str(argus[4]) == "0":
            logger.info("无需执行任何动作")
            return "无需执行任何动作"
        devices_name = []
        for s in devices:
            d_n = self.rds_handler.hget(app_config.devices_history, s)
            if d_n:
                devices_name.append(d_n)
            else:
                devices_name.append(self.resource.getDeviceModelBySn(s))
        devices_name = [d.rstrip('\r') for d in devices_name]
        versioninfo = DevicesManagerTask().get_device_version(devices_name)
        for v in versioninfo.keys():
            useable_v = [i for i in versioninfo[v] if 'dev' in i]
            v_sort = 'qponm'
            for u in list(v_sort):
                if u + '-dev' in useable_v:
                    versioninfo[v] =  u + '-dev'
                    break
            else:
                if len(useable_v) > 0:
                    versioninfo[v] = useable_v[-1]
        print versioninfo
        logger.info("task name is %s" % (params['task_name']))
        logger.info("mi account name is %s" % (params['mi_account_name']))
        sub_task = []
        timing = str(datetime.datetime.now())
        print os.getcwd()
        t_task_name = params['task_name'] + '_' + timing.replace(' ', '_')
        result_dir = "./output/results/" + t_task_name
        os.mkdir(result_dir)
        for sn in devices:
            divideparam = copy.deepcopy(argus)
            divideparam[0] = devices_name[devices.index(sn)]
            divideparam.insert(0, sn)
            if divideparam[1] in versioninfo.keys():
                divideparam[2] = versioninfo[divideparam[1]]
            if self.resource.getDeviceRegionBySn(sn) != 'zh-CN':
                divideparam[3] = "global"
            device_nick_name = self.resource.getDeviceProductNameBySn(divideparam[0])
            divideparam.append(device_nick_name)
            divideparam.append(params['task_name'])
            task_name = app_config.task_prefix + divideparam[1] + '_' + timing
            sub_task.append(task_name)
            divideparam.append(task_name)
            divideparam.append(params['mi_account_name'])
            # result_dir2 = "./output/results/" + params['task_name'] + timing.replace(' ', '_') + '/' + str(
            #     device_nick_name)
            # os.mkdir(result_dir2)
            divideparam.append(result_dir)
            p_name = app_config.expired_key_prefix + divideparam[1] + '_' + timing
            logger.debug("定时任务入参:" + str(divideparam))
            self.rds_handler.monkey_task_insert(task_name, divideparam)
            logger.debug("任务%s创建成功，等待执行" % task_name)
            if int(params['execpolicy']):
                ex_time = calc_exec_during_timing(params['execpolicy'], params['weekdays'], params['iter_time'],
                                                  params['long_time'], params['point_time'])
                logger.debug("任务%s将在%s小时后执行" % (task_name, str(ex_time / 3600.0)))
                self.rds_handler.setex(p_name, ex_time)
            else:
                logger.debug("任务%s将马上执行" % (task_name,))
                self.rds_handler.setex(p_name, 2)
            logger.debug("任务%s创建成功，等待执行" % p_name)
        gettasks = self.rds_handler.get("all_task")
        if gettasks == 'None':
            gettasks = eval(gettasks)
        print 'gettasks', str(gettasks)
        if gettasks is None:
            self.rds_handler.set("all_task", str([t_task_name, ]))
        else:
            print t_task_name
            alltask = eval(gettasks)
            alltask.append(t_task_name)
            print alltask
            self.rds_handler.set("all_task", str(alltask))
        self.rds_handler.set(t_task_name, str(sub_task))
        return "创建任务成功！"

    # def execlinemonkey(self, params):
    #     """
    #     处理走起操作
    #     """
    #     versioninfo = {'ugglite': u'n-dev'}
    #     logger.info("开始执行monkey任务")
    #     # 根据界面操作的结果拼接monkey指令
    #     monkeycmd = "'monkey"
    #     packages = []
    #     packages.extend(params['pkg'].split(';'))
    #     packages.extend(params['package'].split(';'))
    #     # 去重
    #     packages = [p for p in list(set(packages)) if p != ""]
    #     logger.debug("包信息:" + str(packages))
    #     for pg in packages:
    #         monkeycmd += " -p " + pg
    #     monkeycmd += " " + params['loglevel'] + " -s " + params['seed']
    #     for errignore in params['errhandler'].split(';'):
    #         monkeycmd += " " + errignore
    #     if params['pct_touch']:
    #         monkeycmd += " --pct-touch " + params['pct_touch']
    #     if params['pct_motion']:
    #         monkeycmd += " --pct-motion " + params['pct_motion']
    #     if params['pct_trackball']:
    #         monkeycmd += " --pct-trackball " + params['pct_trackball']
    #     if params['pct_nav']:
    #         monkeycmd += " --pct-nav " + params['pct_nav']
    #     if params['pct_majornav']:
    #         monkeycmd += " --pct-majornav " + params['pct_majornav']
    #     if params['pct_syskeys']:
    #         monkeycmd += " --pct-syskeys " + params['pct_syskeys']
    #     if params['pct_appswitch']:
    #         monkeycmd += " --pct-appswitch " + params['pct_appswitch']
    #     if params['pct_anyevent']:
    #         monkeycmd += " --pct-anyevent " + params['pct_anyevent']
    #     monkeycmd += " --throttle " + \
    #                  params['throttle'] + " " + \
    #                  params['eventsnumber'] + " > /sdcard/monkey.log'"
    #     logger.debug("monkey指令信息:" + str(monkeycmd))
    #     # 如果未选择机型，对IDLE状态的机型进行操作，如果选择机型对制定机型进行操作
    #     devices = []
    #     if params['device']:
    #         self.resource.setDeviceWorkStateBusy(str(params['device']))
    #         devices.append(str(params['device']))
    #     else:
    #         self.resource.setAllIdleDevicesBusy()
    #         devices = self.resource.getIdleDevices()
    #     logger.info("参加执行的Android设备有:" + str(devices))
    #     # 构建Process入参，[省略的打包机型， 打包版本， 包适配的区域， 是否需要打包， 是否执行monkey测试， 当前的连接到电脑的设备信息（占时未使用到）， 拼接的monkey测试指令， monkey测试的开始时间]
    #     argus = ["", params['version'], params['area'], params['build'],
    #              params['monkey'], monkeycmd, '0']
    #     if str(argus[3]) == "0" and str(argus[4]) == "0":
    #         logger.info("无需执行任何动作")
    #         return "无需执行任何动作"
    #     # process = []
    #     for sn in devices:
    #         divideparam = copy.deepcopy(argus)
    #         divideparam[0] = self.resource.getDeviceModelBySn(sn)
    #         divideparam.insert(0, sn)
    #         if divideparam[1] in versioninfo.keys():
    #             divideparam[2] = versioninfo[divideparam[1]]
    #         logger.debug("定时任务入参:" + str(divideparam))
    #         # self.worker(divideparam)
    #         aprocess = Process(target=self.worker, args=(divideparam,), name=divideparam[0])
    #         aprocess.daemon = True
    #         aprocess.start()
    #     #     process.append(aprocess)
    #     # logger.debug("子进程启动结束")
    #     # [p.join() for p in process]
    #     logger.debug("任务创建成功，等待执行")
    #     return ""

    def getpackageinfoindevice(self, devicesn):
        """
        获取设备中的包信息
        :param devicesn: 设备的sn号
        :return: 返回包信息
        """
        if not devicesn:
            return ""
        return self.resource.getDeviceBySn(devicesn).getpackageinfoindevice()

    def get_all_tasks_info(self):
        """
        获取monkey测试任务列表
        :return: 返回monkey测试任务列表
        """

        tasklist_final = []
        tasklist = self.rds_handler.hkeys("his_info")
        print tasklist
        tasklist = tasklist[:5]
        print tasklist
        for t in tasklist:
            sub_task_list = eval(self.rds_handler.hget("his_info", str(t)))
            for i in sub_task_list:
                i.update({"date": t})
                tasklist_final.append(i)
        # tasklist = self.rds_handler.keys(app_config.task_prefix + '*')
        # for t in tasklist:
        #     taskinfo = self.rds_handler.hgetall(t)
        #     taskinfo['taskname'] = t
        #     tasklist_final.append(taskinfo)
        # print tasklist_final
        tasklist_resp = {
            "code": 0,
            "msg": "",
            "count": len(tasklist_final),
            "data": tasklist_final
        }
        print tasklist_resp
        return tasklist_resp

    def terminatePid(self, pid):
        logger.info(pid)
        date, pid = pid.split('_')
        self.rds_handler.setex('pk_' + pid + '_' + date, 1)
        return 'ok'
        # while True:
        #     time.sleep(5)
        #     sub_task_list = eval(self.rds_handler.hget("his_info", str(date)))
        #     for i in sub_task_list:
        #         if i['pid'] == pid:
        #             if i['status'] == 'end':
        #                 return 'ok'
